
// === uuNode ===
// depend: uuMeta
/*
uuNode("<div>", ctx = body, pos = last) - return first node
uuNode.text("text", ctx = body, pos = last) - return first text node
uuNode.replace(newNode, oldNode) - return oldNode
uuNode.remove(node) - return node
uuNode.clear(parentNode) - return node
uuNode.substance("<div>", ctx = owner) - return DocumentFragment
uuNode.cutdown(ctx = body) - return DocumentFragment
uuNode.normalize(ctx = body, depth = 0)
 */
(function() {
var _node, // inner namespace
    _mm = uuMeta,
    _win = window,
    _doc = document,
    _enum = {
      FIRST:       1, // uuNode.FIRST - first sibling
      PREV:        2, // uuNode.PREV - prev sibling
      NEXT:        3, // uuNode.NEXT - next sibling
      LAST:        4, // uuNode.LAST - last sibling
      FIRST_CHILD: 5, // uuNode.FIRST_CHILD - first child
      LAST_CHILD:  6  // uuNode.LAST_CHILD - last child
    };

// uuNode - insert Node
_node = function(node,    // @param DocumentFragment/HTMLString:
                 context, // @param Node(= document.body): parent node
                 pos) {   // @param Number(= uuNode.LAST_CHILD): insert position
                          // @return Node: first node
  var rv = node, ctx = context || _doc.body, pn = ctx.parentNode;

  if (typeof node === "string") { // "<div>" to div node
    node = _node.substance(node, ctx);
    rv = node.firstChild;
  }
  switch (pos || 6) {
  case 1: ctx = pn; // break;
  case 5: ctx.firstChild ? ctx.insertBefore(node, ctx.firstChild)
                         : ctx.appendChild(node); break;
  case 4: ctx = pn; // break;
  case 6: ctx.appendChild(node); break;
  case 2: pn.insertBefore(node, ctx); break;
  case 3: (pn.lastChild === ctx) ? pn.appendChild(node)
                                 : pn.insertBefore(node, ctx.nextSibling);
  }
  return rv;
};

_mm.mix(_node, {
  // uuNode.text - insert TEXT_NODE or "TextString"
  text: function(node,    // @param DocumentFragment/TextString:
                 context, // @param Node(= document.body): parent node
                 pos) {   // @param Number(= uuNode.LAST_CHILD): insert position
                          // @return Node: first text node
    return uuNode(typeof node === "string" ? _doc.createTextNode(node)
                                           : node, context, pos);
  },

  // uuNode.replace - replace oldNode
  replace: function(node,      // @param Node: new node
                    oldNode) { // @param Node: old node(cutout)
                               // @return Node: oldNode
    return oldNode.parentNode.replaceChild(node, oldNode);
  },

  // uuNode.remove - remove node 
  remove: function(node) { // @param Node:
                           // @return Node:
    return node.parentNode.removeChild(node);
  },

  // uuNode.clear - clear all children
  clear: function(node) { // @param Node: parent node
    node.innerHTML = "";
    return node; // return node
  },

  // uuNode.substance - convert HTMLString into DocumentFragment
  substance: function(html,      // @param HTMLString:
                      context) { // @param Node: node or owner document
                                 // @return DocumentFragment:
    var rv, range, placeholder;

    // use DOM Level2 Range Module
    if (_doc.createRange && !(_mm.opera && _mm.uaver >= 9.5)) {
      // http://d.hatena.ne.jp/uupaa/20081021/1224525518
      range = _doc.createRange();
      range.selectNode(context);
      return range.createContextualFragment(html);
    }
    rv = _doc.createDocumentFragment();
    placeholder = _doc.createElement("div");
    placeholder.innerHTML = html;
    while (placeholder.firstChild) {
      rv.appendChild(placeholder.removeChild(placeholder.firstChild));
    }
    return rv;
  },

  // uuNode.cutdown - cut all nodes less than context
  cutdown: function(context) { // @Node(= document.body): parent node
                               // @return DocumentFragment:
    var rv, ctx = context || _doc.body;
    if (_doc.createRange) {
      (rv = _doc.createRange()).selectNodeContents(ctx);
      return rv.extractContents(); // return DocumentFragment
    }
    rv = _doc.createDocumentFragment();
    while (ctx.firstChild) {
      rv.appendChild(ctx.removeChild(ctx.firstChild));
    }
    return rv;
  },

  // uuNode.normalize - removes CRLF/blank-text/white-space/comment node
  normalize: function(context, // @param Node(= document.body): parent node
                      depth) { // @param Number(= 0): max depth
    function fn(elm, depth) {
      for (var w = elm.firstChild; w; w = w.nextSibling) {
        switch (w.nodeType) {
        case 1: (depth + 1 <= limit) && fn(w, depth + 1); break; // recursive
        case 3: if (blank.test(w.nodeValue)) { break; } // blank-text node?
        case 8: rv.push(w); // comment node
        }
      }
    }
    var rv = [], v, i = 0, blank = /\S/, limit = depth || 0;

    fn(context, 0);
    while ( (v = rv[i++]) ) {
      v.parentNode.removeChild(v);
    }
  }
});

// --- initialize ---

// --- export ---
_win.uuNode = _node; // window.uuNode
_mm.mix(_node, _enum);

})(); // uuNode scope

